import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;


public class Decompresser implements Commande {	
	
	int longueurTexteOriginal;
	
	ArrayList <Byte>donneesBinaireEncodes = 
        new ArrayList<Byte>();
	
	Hashtable <String,Character>tableDeDecodage = 
        new Hashtable<String,Character>();
	
	String pathFichier="";
	
	String donneesEncodees= "";
	
	String donneesDecodees = "";
	
	Hashtable <Byte,String>bitMapDecode = 
             new Hashtable<Byte,String>();
	
	Hashtable <Character,String>tableDeCodes = new Hashtable<Character,String>();
	
	public void setPath(String path){
		pathFichier = path;
	}
	
	public void execute() {
		
		lireFichierCompresse();	
		construireBitMapDecode();
		decoderBitsString();
		construireTableDeDecodage();
		decoderBitsCaracteres();
		sauvegarderFichierTexte();	
		
	}

	void construireBitMapDecode(){
	    for(int i = 0; i <= 255;i++){
	      StringBuffer buffer = new StringBuffer();
	      if((i & 128) > 0){buffer.append("1");
	        }else {buffer.append("0");};
	      if((i & 64) > 0){buffer.append("1");
	        }else {buffer.append("0");};
	      if((i & 32) > 0){buffer.append("1");
	        }else {buffer.append("0");};
	      if((i & 16) > 0){buffer.append("1");
	        }else {buffer.append("0");};
	      if((i & 8) > 0){buffer.append("1");
	        }else {buffer.append("0");};
	      if((i & 4) > 0){buffer.append("1");
	        }else {buffer.append("0");};
	      if((i & 2) > 0){buffer.append("1");
	        }else {buffer.append("0");};
	      if((i & 1) > 0){buffer.append("1");
	        }else {buffer.append("0");};
	      bitMapDecode.put((byte)(i),buffer.toString());
	    }
	}

	void decoderBitsString(){
		
	    StringBuffer buffer = new StringBuffer();
	    
	    for(Byte element : donneesBinaireEncodes){
	    	
	      byte wholeByte = element;
	      
	      buffer.append(bitMapDecode.get(wholeByte));
	      
	    }    
	    
	    donneesEncodees = buffer.toString();
	    
	}
	
	void construireTableDeDecodage(){
	    Enumeration <Character>enumerator = 
	                                    tableDeCodes.keys();
	    while(enumerator.hasMoreElements()){
	      Character nextKey = enumerator.nextElement();
	      String nextString = tableDeCodes.get(nextKey);
	      tableDeDecodage.put(nextString,nextKey);
	      
	    }
	}
	
	void decoderBitsCaracteres(){
		
	    StringBuffer out = new StringBuffer();
	    StringBuffer buffer = new StringBuffer();
	
	    for(int i = 0;i < donneesEncodees.length();i++){
	    	
	    	buffer.append(donneesEncodees.charAt(i));
	    	
	    	if(tableDeDecodage.containsKey(buffer.toString()))
	    	
	    	{
	    		
	        out.append(
	        		tableDeDecodage.get(buffer.toString()));
	        
	        buffer = new StringBuffer();
	    	}
	    }
	    
	    donneesDecodees = out.toString();	   
	    
  }
	
	void lireFichierCompresse() {
		
		try{			
						
			ObjectInputStream oips = new ObjectInputStream(new FileInputStream(pathFichier));		
						
			tableDeCodes=(Hashtable<Character, String>)oips.readObject();
			longueurTexteOriginal=oips.readInt();
			
			System.out.println(tableDeCodes.get('a'));
			System.out.println(longueurTexteOriginal);
			
			boolean eof=false;
			
			while (!eof) 			
			{
				try
			
				{					
					donneesBinaireEncodes.add(oips.readByte());	
					
				}		
				
				catch(EOFException e) 				
				{
					eof=true;
					
				}
			}
			
			oips.close();
		}		
		
		catch (Exception e){
			
			System.out.println(e.toString());
		}		
		
	}
	
	void sauvegarderFichierTexte(){
		
		PrintWriter sortie;
		try {
			sortie = new PrintWriter (new FileWriter(pathFichier.substring(0,pathFichier.length()-3)));
			System.out.println(donneesDecodees);
			sortie.write(donneesDecodees.substring(0,longueurTexteOriginal));
			sortie.close();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}				
		
	}
	
}
